#!/usr/bin/env python3
# -*- coding:utf-8 -*-
#
# Copyright 2013 suliu.net
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#codeby     道长且阻
#email      ydhcui@suliu.net/QQ664284092
#website    http://www.suliu.net

import os,sys
import time
import logging
import threading
import random
import ctypes
import util
from models import *
from SmartQQ import QQapi
from core import Core



def inputbox(title=None,default=None):
    try:
      result = raw_input(title)
    except:
      result = input(title)
    return  result if result else default

USERNAME=inputbox(u"输入QQ号码:")
PASSWORD=inputbox("输入QQ密码:")
try:
    conf = Setting.get(Setting.username==USERNAME)
except Setting.DoesNotExist:
    Setting.create(username=USERNAME,password=PASSWORD)
    conf = Setting.get(Setting.username==USERNAME)
if conf.password != PASSWORD:
    Setting.update(password=PASSWORD).where(Setting.username==USERNAME).execute()
    conf = Setting.get(Setting.username==USERNAME)

#配置区
ADMINQQ =[664284092]
######################
SELFNAME=conf.botname
AUTORE  =0#conf.isautore
SYSLOG  =conf.issyslog
CHATLOG =conf.ischatlog
PATH    = os.path.dirname(sys.argv[0])

#初始化
if not os.path.exists(util.getpath('res')):
    os.mkdir(util.getpath('res'))

QQ = QQapi(USERNAME,PASSWORD)
CORE = Core(USERNAME)

#日志
logger = logging.getLogger("WALLE")
stream_handler = logging.StreamHandler(sys.stderr)
logger.addHandler(stream_handler)
logger.setLevel(logging.INFO)
if SYSLOG:
    formatter = logging.Formatter('%(name)-12s %(asctime)s %(levelname)-8s \n%(message)s', '%a, %d %b %Y %H:%M:%S',)
    file_handler = logging.FileHandler(util.getpath("sys.log"))
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

#公共函数
#ctypes 更改cmd字体颜色
ctypes.windll.Kernel32.GetStdHandle.restype = ctypes.c_ulong
ConsoleText = ctypes.windll.Kernel32.GetStdHandle(ctypes.c_ulong(0xfffffff5))
WHND =  ctypes.windll.kernel32.GetConsoleWindow()
def pprint(*s):
    ctypes.windll.Kernel32.SetConsoleTextAttribute(ConsoleText,random.randint(1,16))
    logger.info('\n'.join(s))


class Bot(object):

   def sleep(self,content,fromuin):
       conf = Setting.select().where(Setting.username==USERNAME).get()
       STARTKEY=conf.startkey
       ENDKEY  =conf.endkey
       STARTMSG=conf.startmsg
       ENDMSG  =conf.endmsg
       if STARTKEY in content:
           if fromuin in self.grouplist:
               self.grouplist.remove(fromuin)
               QQ.send_group_msg(fromuin,STARTMSG)
       if ENDKEY in content:
           if fromuin not in self.grouplist:
               self.grouplist.append(fromuin)
               QQ.send_group_msg(fromuin,ENDMSG)
       if content[:3]==self.adminhead:
          cmd=content[3:]
          if cmd=='CHATON':
              self.groups[fromuin]['chatmode']=1
              QQ.send_group_msg(fromuin,str(self.groups[fromuin]))
          if cmd=='CHATOFF':
              self.groups[fromuin]['chatmode']=0
              QQ.send_group_msg(fromuin,str(self.groups[fromuin]))
          if cmd=='CMDON':
              ctypes.windll.user32.ShowWindow(WHND, 1)#显示窗口
              ctypes.windll.kernel32.CloseHandle(WHND)
          if cmd=='CMDOFF':
              ctypes.windll.user32.ShowWindow(WHND, 0)#隐藏窗口
              ctypes.windll.kernel32.CloseHandle(WHND)

   def admin(self,content,fromuin):
       if content[:3]==self.adminhead:
          content=content[3:].replace('os','OS').replace('sys','SYS')
          print('\a')
          _globals=globals()
          _globals.update({'SELF':self})
          _globals.update({'UIN':fromuin})
          try:
              E = 'ok'
              #_globals.update({'E':E})
              exec(content,_globals)
          except Exception as e:
              E = str(e)
          if fromuin in self.friends.keys():
             QQ.send_user_msg(fromuin,str(E))
          else:
             QQ.send_group_msg(fromuin,str(E))

   def makeface(self,face=None):
       face=random.choice(range(88))
       return face

   def __init__(self):
       self.friends = {}   #好友字典
       self.groups = {}    #群字典
       self.grouplist = [] #黑名单
       self.adminhead = "$$$"

   def run(self):
       while True:
           data = QQ.Queue.get()
           if data:
              threading.Thread(target=self.poll,args=(data,)).start()

   def poll(self, data):
      if SYSLOG:
          pprint(str(data))
      for msg in data:
         if msg=='timeout':
            QQ.login()
         else:
            polltype = msg['poll_type']                           #消息类型
            if polltype=="sess_message":                          #临时会话
               pass

            elif polltype == 'message':                           #个人消息
               print('\a')                                        #发出bebe声
               fromuin = msg['value']['from_uin']                 #消息来源QQ
               content = ''.join([v for v in msg['value']['content'] if type(v)!=type([])]).strip()    #去除了表情的消息内容
               if fromuin not in [uin for uin in self.friends.keys()]:
                  self.friends[fromuin]={}
                  sendqq = QQ.get_uin2qq(fromuin)
                  self.friends[fromuin]['qq']=sendqq
               sendqq=self.friends[fromuin]['qq']
               pprint("收到来自 QQ(%s),UIN(%s) 的消息 \n (%s)。\n" %(sendqq,fromuin,content))
               if sendqq in ADMINQQ and content[:3]==self.adminhead:
                  return self.admin(content,fromuin)
               if CHATLOG:
                   Logs.create(fromqq=sendqq, toqq=USERNAME, content=content)
               if content and content[:1]!='#':
                  content="#%s"%content
               data=CORE.auto(content,sendqq)
               if data:
                  QQ.send_user_msg(fromuin,data)
                  pprint("发送个人消息 (%s) \n (%s) 。\n" %(sendqq,data))
                  if CHATLOG:
                      Logs.create(fromqq=USERNAME, toqq=sendqq, content=data)
               else:
                   QQ.send_user_msg(fromuin,face=self.makeface())       #如果是表情就也回应表情

            elif polltype == 'group_message':                      #群消息
               fromuin = msg['value']['from_uin']                  #消息来源QQ群
               content = ''.join([v for v in msg['value']['content'] if type(v)!=type([])]).strip()  #去除了表情的消息内容
               senduin = msg['value']['send_uin']                  #消息发送者
               if senduin not in [uin for uin in self.friends.keys()]:
                  self.friends[senduin]={}
                  sendqq = QQ.get_uin2qq(senduin)
                  self.friends[senduin]['qq']=sendqq
               sendqq=self.friends[senduin]['qq']
               if fromuin not in self.groups.keys():
                   self.groups[fromuin]={'chatmode':0}
               self.sleep(content,fromuin)
               if sendqq in ADMINQQ and content[:3]==self.adminhead:
                  return self.admin(content,fromuin)
               pprint("收到来自群(%s) 里 (%s) 发来的消息 \n (%s)。\n" %(fromuin,senduin,content))
               if fromuin not in self.grouplist:
                  if self.groups[fromuin]['chatmode'] and content and content[:1]!='#':
                     content='#'+content
                  data=CORE.auto(content,sendqq)
                  if data:
                     QQ.send_group_msg(fromuin,data)
                     pprint("发送群消息 (%s) \n (%s) 。\n" %(fromuin,data))
                  else:
                     if self.groups[fromuin]['chatmode'] or content[:1]=='#':
                        QQ.send_group_msg(fromuin,self.makeface())

            elif polltype == 'discu_message':                     #讨论组消息
               fromuin = msg['value']['did']                  #消息来源
               content = ''.join([v for v in msg['value']['content'] if type(v)!=type([])]).strip()  #去除了表情的消息内容
               senduin = msg['value']['send_uin']                  #消息发送者
               if senduin not in [uin for uin in self.friends.keys()]:
                  self.friends[senduin]={}
                  sendqq = QQ.get_uin2qq(senduin)
                  self.friends[senduin]['qq']=sendqq
               sendqq=self.friends[senduin]['qq']
               if fromuin not in self.groups.keys():
                   self.groups[fromuin]={'chatmode':0}
               self.sleep(content,fromuin)
               if sendqq in ADMINQQ and content[:3]==self.adminhead:
                  return self.admin(content,fromuin)
               pprint("收到来自群(%s) 里 (%s) 发来的消息 \n (%s)。\n" %(fromuin,senduin,content))
               if fromuin not in self.grouplist:
                  if self.groups[fromuin]['chatmode'] and content and content[:1]!='#':
                     content='#'+content
                  data=CORE.auto(content,sendqq)
                  if data:
                     QQ.send_discu_msg(fromuin,data)
                     pprint("发送群消息 (%s) \n (%s) 。\n" %(fromuin,data))
                  else:
                     if self.groups[fromuin]['chatmode'] or content[:1]=='#':
                        QQ.send_discu_msg(fromuin,face=self.makeface())
            elif polltype == 'buddies_status_change':             #状态改变
               pass

            elif polltype == 'ptwebqq':
               QQ.cookie.update({'ptwebqq':msg['p']})

            elif polltype == 'kick_message':                      #被下线
               util.SendMail(USERNAME,PASSWORD).send(
                   ['%s@qq.com'%qq for qq in ADMINQQ],"被下线kick_message",str(msg)
               )
               print('\a'*110)#警报声响起~~
               QQ.login()
            elif polltype == 'system_message':                    #系统消息
               fromuin=msg['value']['account']
               QQ.allow_add_friend(fromuin)
               pprint("接受( %s )的好友请求。" %(fromuin))

            else:
               pass


#main start ...
threading.Thread(target=QQ.login).start()
threading.Thread(target=Bot().run).start()








